package com.backstage.controller.login;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.backstage.entity.po.SysPermission;
import com.backstage.entity.po.SysUser;
import com.backstage.service.ISysPermissionService;
import com.backstage.service.ISysUserService;
import com.common.constants.GlobalConstants;



/**
 * 
 * @author wangkun
 *
 */
public class SystemAuthorizingRealm extends AuthorizingRealm {
	
	@Autowired
	private ISysUserService systemUserService;
	@Autowired
	private ISysPermissionService sysPermissionService;
	
	private static final Integer MAIN_MENU = 1;
	
	@Override
	public void setName(String name) {
		super.setName("SystemAuthorizingRealm");
	}
	/**
	 * 认证回调函数, 登录时调用
	 * Shiro登录认证(原理：用户提交 用户名和密码  --- shiro 封装令牌 ---- realm 通过用户名将密码查询返回 ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制
	 * 该方法的调用时机为LoginController.login()方法中执行Subject.login()时 
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
			throws AuthenticationException {
		// 获取基于用户名和密码的令牌：实际上这个authcToken是从LoginController里面currentUser.login(token)传过来的
		UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
		SysUser systemUser = systemUserService.findSysUserByUserCode(token.getUsername());
		Session session = SecurityUtils.getSubject().getSession();
		if (systemUser == null) {
			throw new UnknownAccountException("账号不存在");
		}
		// 校验用户状态
		if (GlobalConstants.NO.equals(systemUser.getLocked().toString())) {
			throw new LockedAccountException("账号被锁");
		}
		//校验密码和用户
		if(!systemUser.getUsercode().equals(token.getUsername())){
			throw new IncorrectCredentialsException("用户名错误");
		}
		//左侧菜单
		findMenu(systemUser);
		//快捷菜单
		findShortcutMenu(systemUser);
		// 认证缓存信息
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(systemUser, systemUser.getPassword(),ByteSource.Util.bytes(systemUser.getSalt()),this.getName());
		session.setAttribute("currentUser", systemUser);
		return simpleAuthenticationInfo;
	}
	/**
	 *  用于授权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		//从 principals获取主身份信息
		//将getPrimaryPrincipal方法返回值转为真实身份类型（在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型），
		SysUser sysUser = (SysUser)principals.getPrimaryPrincipal();
		if(null == sysUser){
			return null;
		}
		//根据身份信息获取权限信息
		//从数据库获取到权限数据
		List<SysPermission> sysPermissionsList = null;
		try {
			sysPermissionsList = sysPermissionService.findPermissionListByUserId(sysUser.getId());
		} catch (Exception e) {
			e.printStackTrace();
		}
		List<String> permissions = new ArrayList<String>();
		if(null != sysPermissionsList){
			for(SysPermission sysPermission:sysPermissionsList){
				permissions.add(sysPermission.getPercode());
			}
		}
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		simpleAuthorizationInfo.addStringPermissions(permissions);
		return simpleAuthorizationInfo;
	}
	
	/**
	 * 查找用户菜单
	 * @param userVo
	 */
	private void findMenu(SysUser sysUser){
		List<SysPermission> allMenus = null;
		List<SysPermission> mainMenus = new LinkedList<SysPermission>();
		List<SysPermission> subMenus = null;
		try {
			allMenus = sysPermissionService.findUserMenu(sysUser.getId());
			for(SysPermission allMenu:allMenus){
				if(allMenu.getParentid() == MAIN_MENU){
					mainMenus.add(allMenu);
				}
			}
			for(SysPermission permission:mainMenus){
				subMenus = new LinkedList<SysPermission>();
				for(SysPermission subMenu:allMenus){
					if(permission.getId().equals(subMenu.getParentid())){
						subMenus.add(subMenu);
					}
				}
				permission.setSubMenus(subMenus);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		sysUser.setMenus(mainMenus);
	}
	
	/**
	 * 查找快捷菜单
	 * @param sysUser
	 */
	private void findShortcutMenu(SysUser sysUser){
		List<SysPermission> shortcutMenu = sysPermissionService.findShortcutMenu(sysUser.getId());
		sysUser.setShortcutMenu(shortcutMenu);
	}

}
